package com.spacearcade.logic.runtime;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import android.util.Log;

import com.spacearcade.common.layers.IApplicationLayer;
import com.spacearcade.common.layers.commands.CommandRequest;
import com.spacearcade.common.model.IModel;
import com.spacearcade.graphic.GameManager;
import com.spacearcade.logic.Dot;
import com.spacearcade.logic.LogicModel;
import com.spacearcade.logic.ObjectType;
import com.spacearcade.logic.SpaceObject;

public class LogicRunner implements IApplicationLayer {

	private int iterationGap = 2;
	private double timeSpan = 10;

	List<CommandRequest> commands = Collections
			.synchronizedList(new ArrayList<CommandRequest>());
	Map<String, SpaceObject> logicObjects = new LinkedHashMap<String, SpaceObject>();

	private volatile boolean bStop = false;

	public void start() {
		new Thread() {

			public void run() {
				while (!bStop) {
					Log.e("SpaceArcade", "run Logic Runner");
					ArrayList<CommandRequest> commandsForIteration = new ArrayList<CommandRequest>();
					synchronized (commands) {
						commandsForIteration.addAll(commands);
						commands.clear();

						performCommands(commandsForIteration);

						simulateLogic();

					}

					try {
						sleep(iterationGap);
					} catch (InterruptedException e) {
						System.out.println("LogicRunner.run() -> interrupted");
						return;
					}
				}
			}

		}.start();
	}

	public void stop() {
		bStop = true;
	}

	private void simulateLogic() {
		// TODO: add event support!
		new ArrayList<Object>();
		Log.v("SpaceArcade", "LogicRunner.simulateLogic() -> simulating "
				+ logicObjects.size() + " objects");
		for (SpaceObject model : logicObjects.values()) {
			// move all the objects

			model.mooveForward();

			for (SpaceObject tModel : logicObjects.values()) {
				if (model != tModel) {
					if (model.type == tModel.type
							&& tModel.type == ObjectType.Bullet) {
						continue;
					}
					ArrayList<Dot> list = model.meet(tModel);
					if (list != null) {
						model.mooveBackward();
						tModel.mooveBackward();
						model.kick(tModel, list.get(0), list.get(1));
						if (tModel.type == ObjectType.Bullet) {
							tModel.alive = false;
						}
					}
				}
			}

			if (model.x < model.radius && model.dx < 0) {
				model.dx *= -1;
			}
			if (model.x > GameManager.FIELD_WIDTH - model.radius
					&& model.dx > 0) {
				model.dx *= -1;
			}
			if (model.y < model.radius && model.dy < 0) {
				model.dy *= -1;
			}
			if (model.y > GameManager.FIELD_HEIGHT - model.radius
					&& model.dy > 0) {
				model.dy *= -1;
			}

		}
	}

	private void performCommands(Collection<CommandRequest> commandsForIteration) {
		for (CommandRequest cmd : commandsForIteration) {
			switch (cmd.getType()) {
			case CreateObject:
				System.out
						.println("LogicRunner.performCommands() -> creating object_asteroid");

				try {
					SpaceObject model = new SpaceObject(
							Integer.parseInt(cmd.getParameters().get("x")),
							Integer.parseInt(cmd.getParameters().get("y")),
							Double.parseDouble(cmd.getParameters().get("angle")),
							Double.parseDouble(cmd.getParameters().get("speed")),
							Enum.valueOf(ObjectType.class, cmd.getParameters()
									.get("type")));
					logicObjects.put(model.toString(), model);
				} catch (Exception e) {
					System.out.print(e.getMessage());
				}

				break;
			case DeleteObject:
				System.out
						.println("LogicRunner.performCommands() -> removing object");

				logicObjects.remove(cmd.getTargetID());
				break;

			case PropertySet:
				System.out
						.println("LogicRunner.performCommands() -> changing object");

				break;
			default:
				break;
			}
		}
	}

	public void pushCommands(CommandRequest... cmd) {
		System.out.println("LogicRunner.pushCommands()");
		commands.addAll(Arrays.asList(cmd));
	}

	public Collection<? extends IModel> createObjectsView() {
		synchronized (commands) {
			System.out.println("LogicRunner.createObjectsView()");

			ArrayList<IModel> viewObjects = new ArrayList<IModel>(
					logicObjects.size());
			for (SpaceObject model : logicObjects.values()) {
				viewObjects.add(model.createView());
			}

			return viewObjects;
		}
	}

}
